// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <melon/varint.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <pollux/dwio/dwrf/common/int_encoder.h>

using namespace ::testing;

namespace kumo::pollux::dwrf {

class VarintPairs {
 public:
  const uint64_t value;
  const std::vector<uint8_t> varInt;

  VarintPairs(uint64_t value, std::vector<uint8_t> varInt)
      : value{value}, varInt{varInt} {}
};

TEST(TestIntEncoder, TestVarIntEncoder) {
  auto values = std::vector<VarintPairs>{
      {0, {0x0}},
      {(1ul << 7) - 1, {0x7F}},
      {(1ul << 7), {0x80, 0x1}},
      {(1ul << 14) - 1, {0xFF, 0x7F}},
      {(1ul << 14), {0x80, 0x80, 0x01}},
      {(1ul << 21) - 1, {0xFF, 0xFF, 0x7F}},
      {(1ul << 21), {0x80, 0x80, 0x80, 0x01}},
      {(1ul << 28) - 1, {0xFF, 0xFF, 0xFF, 0x7F}},
      {(1ul << 28), {0x80, 0x80, 0x80, 0x80, 0x01}},
      {(1ul << 35) - 1, {0xFF, 0xFF, 0xFF, 0xFF, 0x7F}},
      {(1ul << 35), {0x80, 0x80, 0x80, 0x80, 0x80, 0x01}},
      {(1ul << 42) - 1, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}},
      {(1ul << 42), {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}},
      {(1ul << 49) - 1, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}},
      {(1ul << 49), {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}},
      {(1ul << 56) - 1, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}},
      {(1ul << 56), {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}},
      {(1ul << 63) - 1, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}},
      {(1ul << 63),
       {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}},
      {UINT64_MAX,
       {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01}},

  };

  char outBuff[melon::kMaxVarintLength64];

  for (auto& pair : values) {
    auto result = IntEncoder<true>::write64Varint(pair.value, outBuff);
    EXPECT_EQ(result, pair.varInt.size()) << " value " << pair.value;
    ASSERT_THAT(pair.varInt, ElementsAreArray(outBuff, result))
        << " value " << pair.value;
  }
}

} // namespace kumo::pollux::dwrf
